package com.kingyea.app.market.market.controller;

import com.alibaba.fastjson.JSON;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.kingyea.app.market.appBaseInfo.bean.AppBaseInfo;
import com.kingyea.app.market.applicationType.bean.ApplicationType;
import com.kingyea.app.market.applicationType.service.ApplicationTypeService;
import com.kingyea.app.market.area.controller.AreaController;
import com.kingyea.app.market.client.*;
import com.kingyea.app.market.condition.AllCondition;
import com.kingyea.app.market.dept.bean.Organization;
import com.kingyea.app.market.dept.bean.OrganizationVo;
import com.kingyea.app.market.market.bean.Market;
import com.kingyea.app.market.market.service.MarketService;
import com.kingyea.app.market.marketorg.bean.MarketOrg;
import com.kingyea.app.market.marketorg.bean.MarketOrgPo;
import com.kingyea.app.market.supplierAllocation.bean.SupplierAllocation;
import com.kingyea.app.market.supplierAllocation.service.SupplierAllocationService;
import com.kingyea.app.market.utils.BasePage;
import com.kingyea.app.market.utils.ExceptionConditions;
import com.kingyea.app.market.utils.GlobalVar;
import com.kingyea.app.market.utils.StateCode;
import com.kingyea.app.market.utils.page.PageInfo;
import com.kingyea.mobilepolice.system.Result;
import com.kingyea.mobilepolice.system.aspect.NotResult;
import com.kingyea.mobilepolice.system.exception.BusinessException;
import com.kingyea.mobilepolice.user.bean.User;
import com.kingyea.mobilepolice.util.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author
 * @version v1.0.0
 * @description Market 控制层
 * @date Created in 2018-02-10 16:12:21
 */
@RequestMapping(value = "/market")
@RestController
public class MarketController {

    private static final Logger LOGGER = LoggerFactory.getLogger(MarketController.class);
    static LoadingCache<String, String> cacheMap = CacheBuilder.newBuilder() // 缓存接口这里是LoadingCache，LoadingCache在缓存项不存在时可以自动加载缓存
            .concurrencyLevel(4)// 设置并发级别为8，并发级别是指可以同时写缓存的线程数
//            .weakKeys()// 通过 == 运算符来判断是否相等
//            .weakValues()
//            .softValues()
//            .initialCapacity(1000)
            .maximumSize(1000)// 设置缓存最大容量为XX，超过XX之后就会按照LRU最近虽少使用算法来移除缓存项
            .expireAfterWrite(5, TimeUnit.SECONDS)// 设置写缓存后X时间后过期
            // build方法中可以指定CacheLoader，在缓存不存在时通过CacheLoader的实现自动加载缓存
            .build(new CacheLoader<String, String>() {
                public String load(String key) throws Exception {
                    Thread.sleep(200);
                    String val = UUID.randomUUID().toString().replaceAll("-", "");
//                    cacheMap.put(key,val);
                    return val;
                }
            });
    @Autowired
    private MarketService marketService;
    @Autowired
    private AppBaseInfoServiceClient appBaseInfoServiceClient;
    @Autowired
    private SupplierAllocationService supplierAllocationService;
    @Autowired
    private ApplicationTypeService applicationTypeService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RoleServiceClient roleServiceClient;
    @Autowired
    private DictionaryServiceServiceClient dictionaryServiceServiceClient;
    @Autowired
    private OrganizationServiceClient organizationServiceClient;
    /**
     * 市场覆盖的组织机构缓存
     */
    //     Cache<String, Organization> organizationCacheMap = CacheBuilder.newBuilder()
    // CacheBuilder的构造函数是私有的，只能通过其静态方法newBuilder()来获得CacheBuilder的实例
    LoadingCache<String, Organization> organizationCacheMap = CacheBuilder.newBuilder() // 缓存接口这里是LoadingCache，LoadingCache在缓存项不存在时可以自动加载缓存
            .concurrencyLevel(4)// 设置并发级别为8，并发级别是指可以同时写缓存的线程数
//            .weakKeys()// 通过 == 运算符来判断是否相等
//            .weakValues()
//            .softValues()
//            .initialCapacity(1000)
            .maximumSize(1000)// 设置缓存最大容量为XX，超过XX之后就会按照LRU最近虽少使用算法来移除缓存项
            .expireAfterWrite(12, TimeUnit.HOURS)// 设置写缓存后X时间后过期
            // build方法中可以指定CacheLoader，在缓存不存在时通过CacheLoader的实现自动加载缓存
            .build(new CacheLoader<String, Organization>() {
                public Organization load(String key) throws Exception {
                    System.out.println(" -------------------------- 该 org key 需要重新加载： " + key);
                    Result<Organization> orgResult = organizationServiceClient.getBySerialNo(key);//  根据关联信息中的orgId 获取orgName
                    if (orgResult != null && orgResult.getData() != null && StateCode.OPERATION_SUCCESS.equals(orgResult.getCode())) {
                        organizationCacheMap.put(key, orgResult.getData());
                        return orgResult.getData();
                    } else {
                        return null;
                    }
                }
            });
    @Autowired
    private UserServiceClient userServiceClient;

    public static void main(String[] args) throws Exception {
        cacheMap.put("1", "11111");
        cacheMap.put("2", "22222");
        cacheMap.put("3", "33333");
        cacheMap.put("4", "44444");
        cacheMap.put("5", "55555");
        cacheMap.put("6", "66666");

        for (Integer i = 1; i <= 6; i++) {
            System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            for (String s : cacheMap.asMap().keySet()) {
                System.out.println(s.toString() + " >> " + cacheMap.get(s));
            }
        }

        Thread.sleep(5000);
        for (Integer j = 1; j <= 6; j++) {
            System.out.println("??????????????????????????????????????????????????????????????");
            for (Integer i = 1; i <= 6; i++) {
                System.out.println(i.toString() + " >> " + cacheMap.get(i.toString()));
            }
        }


    }

    /**
     * 查询全部
     *
     * @param
     * @return
     */
    @RequestMapping(method = RequestMethod.GET)
    public Object list() throws Exception {
        return marketService.list(null);
    }

    /**
     * 通用查询list
     *
     * @param
     * @return
     */
    @RequestMapping(value = "/queryList", method = RequestMethod.POST)
    public Object queryList(@RequestBody Map<String, Object> map) throws Exception {
        return marketService.queryList(map);
    }

    /**
     * 根据条件查询
     * coverageRange 该变量等于1 的时候，会耗费大量资源去查询该市场所发布到的区域，即：覆盖范围
     *
     * @param
     * @return
     */
    @RequestMapping(value = "/condition", method = RequestMethod.POST)
    public Object conditionQuery(@RequestBody Map<String, Object> market) throws Exception {
        System.out.println("查询市场列表-------------------------");
        Object result = marketService.list(market);
        PageInfo pageInfo = (PageInfo) result;
        List marketObjList = pageInfo.getList();

        if (market.containsKey("coverageRange") && !StringUtils.isEmpty(market.get("coverageRange")) && market.get("coverageRange").toString().equals("1")) {
            List marketObjAndCoverageRangeList = new ArrayList();
            for (Object marketObj : marketObjList) {
                Map<String, Object> marketMap = JSON.parseObject(JSON.toJSONString(marketObj), Map.class);
                AllCondition allCondition = new AllCondition();
                allCondition.setMarketCode((Integer.valueOf(marketMap.get("marketCode") + "")));
                allCondition.setPageAble(false);
                List<MarketOrg> marketOrgs = marketService.getMarketOrgList(allCondition);// 根据市场id 查询该市场的覆盖组织机构关联信息

                String coverageRange = "";
                for (MarketOrg marketOrg : marketOrgs) {
                    Organization organization = null;
                    try {
                        organization = organizationCacheMap.get(marketOrg.getOrgSerialNo());//该方法会触发 自动更新值逻辑,但是会报错
                    } catch (Exception e) {
                        LOGGER.warn("组织机构缓存获取失败：" + marketOrg.getOrgSerialNo() + "  err:" + e.getMessage());
                    }
                    if (organization != null && !StringUtils.isEmpty(organization.getName().trim())) {
                        coverageRange = coverageRange + organization.getName().trim() + ",";
                    }
                }

                marketMap.put("coverageRange", coverageRange);
                marketObjAndCoverageRangeList.add(marketMap);
            }
            pageInfo.setList(marketObjAndCoverageRangeList);
        }
        return pageInfo;
    }

    /**
     * 通过ID查找对象
     *
     * @param marketCode
     * @return
     */
    @RequestMapping(value = "/{marketCode}", method = RequestMethod.GET)
    public Object detail(@PathVariable(value = "marketCode") String marketCode) throws Exception {
        System.out.println(GlobalVar.adminMarket);
        System.out.println(GlobalVar.FILE_HOST);
        System.out.println(GlobalVar.getIsDev());
        return marketService.getById(marketCode);
    }

    /**
     * 通过ID查找对象
     *
     * @param marketCode
     * @return
     */
    @NotResult
    @RequestMapping(value = "/getMarketObj/{marketCode}", method = RequestMethod.GET)
    public Object getMarketObj(@PathVariable(value = "marketCode") String marketCode) throws Exception {
        return marketService.getById(marketCode);
    }

    /**
     * 创建
     *
     * @param market
     * @return
     */
    @RequestMapping(value = "/addMarket", method = RequestMethod.POST)
    public Object create(@RequestBody Map<String, Object> market) throws Exception {
        Object object = market.get("xzqh");
//    	String adminArea = JSON.toJSONString(object);
        market.put("adminArea", object);

        //判断是否已经存在
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("_marketName", market.get("marketName"));// _marketName 故意指定该变量，用=查询
//    	map.put("adminArea", object);
        PageInfo re = (PageInfo) marketService.list(map);
        List<Market> list = re.getList();
        if (list.size() > 0) {
            Result results = new Result();
            results.setCode("B100001");
            return results;
        }

    	/*List parseObject = JSON.parseObject(adminArea, List.class);
    	System.out.println(JSON.toJSONString(parseObject));*/
        Result<User> result = userServiceClient.getCurrentUserInfo();
        User user = result.getData();
        market.put("creater", user.getName());
        return marketService.save(market);
    }

    /**
     * 更新
     *
     * @param market
     * @return
     */
    @RequestMapping(value = "/editMarket", method = RequestMethod.POST)
    public Object update(@RequestBody Map<String, Object> market) throws Exception {
        Object object = market.get("xzqh");
//    	String adminArea = JSON.toJSONString(object);
        market.put("adminArea", object);
        return marketService.update(market);
    }

    /**
     * 删除
     *
     * @param market
     * @return
     */
    @RequestMapping(value = "/deleteMarket", method = RequestMethod.POST)
    public Object delete(@RequestBody Market market) throws Exception {
        int deleteById = 0;
        try {
            SupplierAllocation supplierAllocation = new SupplierAllocation();
            supplierAllocation.setMarketCode(market.getMarketCode());
            Map<String, Object> obMap = new HashMap<String, Object>();
            obMap.put("marketCode", market.getMarketCode());
            PageInfo obj = (PageInfo) supplierAllocationService.list(obMap);
            List<SupplierAllocation> list = (List<SupplierAllocation>) obj.getList();
            List<ApplicationType> byMarket2 = applicationTypeService.getByMarket(market.getMarketCode());
            Result resultObj = appBaseInfoServiceClient.getByMarket(market.getMarketCode());
            List<AppBaseInfo> AppBaseInfoList = (List<AppBaseInfo>) resultObj.getData();
            if (AppBaseInfoList.size() + byMarket2.size() + list.size() == 0) {
                deleteById = marketService.deleteById(market.getMarketCode());
            } else {
                Result results = new Result();
                results.setCode("B100001");
                return results;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(StateCode.SYSTEM_ERROR, StateCode.getMsg(StateCode.SYSTEM_ERROR));
        }
        return deleteById;
    }

    @RequestMapping(value = "/appList/marketList", method = RequestMethod.POST)
    public Object marketList() {
        List<Market> marketByUser = null;
        try {
            marketByUser = marketService.getMarketByUser("U0001");
        } catch (Exception e) {
        }
        return marketByUser;

    }

    /**
     * 关联查询  找出供应商已有权限的市场和未有权限的市场
     *
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getListBySupplier", method = RequestMethod.POST)
    public Object getListBySupplier(@RequestBody Map<String, Object> obj) throws Exception {
        return marketService.getListBySupplier(obj);
    }

    @RequestMapping(value = "/getAreaList", method = RequestMethod.POST)
    public Object getAreaList(@RequestBody Map<String, Object> obj) throws Exception {
        String code = obj.get("code").toString();
        List areaLsit = JSON.parseObject(String.valueOf(redisTemplate.opsForValue().get(AreaController.area_subset_prefix + code)), List.class);
        return areaLsit;
    }

    /**
     * @Description: 市场刷新部门依赖
     * @Param: [po]
     * @return: java.lang.Object
     * @Author: cxc
     * @Date: 2018.04.27 18:07
     */
    @NotResult
    @PostMapping("/org/update")
    public Object orgBatchSave(@RequestBody MarketOrgPo po) {
        ExceptionConditions.checkNotNull(po.getMarketOrgs(), StateCode.NO_ARGUMENT_ERROR);
        ExceptionConditions.checkNotNull(po.getMarketCode(), StateCode.NO_ARGUMENT_ERROR);

        if (po.getMarketOrgs().size() > 0) {
            AllCondition condition = new AllCondition();
            condition.setPageAble(false);
            Object obj = organizationServiceClient.queryByCondition(condition);
            Result result = JSON.parseObject(JSON.toJSONString(obj), Result.class);
            BasePage basePage = JSON.parseObject(JSON.toJSONString(result.getData()), BasePage.class);
            List<Organization> allOrgList = JSON.parseArray(JSON.toJSONString(basePage.getList()), Organization.class);

            List<MarketOrg> orgList = po.getMarketOrgs().stream().filter(o -> !o.getOrgParentSerialNo().equals("-1")).collect(Collectors.toList());
            List<Organization> orgAndChuildList = Lists.newArrayList();
            orgList.stream().forEach(org -> {
                orgAndChuildList.addAll(getChuild2(allOrgList, org.getOrgSerialNo()));
            });
            po.getMarketOrgs().addAll(
                    orgAndChuildList.stream().map(org -> {
                        MarketOrg morg = new MarketOrg();
                        morg.setOrgParentSerialNo(org.getParentSerialNo());
                        morg.setOrgSerialNo(org.getOrgSerialNo());
                        return morg;
                    }).collect(Collectors.toList())
            );
        }
        return marketService.batchSaveOrg(po);
    }

    public List<Organization> getChuild2(List<Organization> list, String orgSerialNo) {
        List<Organization> orgList = getChuild(list, orgSerialNo);
        if (!orgList.isEmpty()) {
            List<Organization> orgList2 = Lists.newArrayList(orgList);
            orgList.stream().forEach(org -> {
                orgList2.addAll(getChuild2(list, org.getOrgSerialNo()));
            });
            return orgList2;
        } else {
            System.out.println("=============没了");
        }
        return orgList;
    }

    public List<Organization> getChuild(List<Organization> list, String orgSerialNo) {
        return list.stream().filter(org -> orgSerialNo.equals(org.getParentSerialNo())).collect(Collectors.toList());
    }

    /**
     * @Description: 市场所有部门id集合，用于树结构显示选中
     * @Param: [obj]
     * @return: java.lang.Object
     * @Author: cxc
     * @Date: 2018.04.27 15:02
     */
    @NotResult
    @PostMapping("/org/list")
    public Object orgList(@RequestBody AllCondition condition) {
        ExceptionConditions.checkNotNull(condition.getMarketCode(), StateCode.NO_ARGUMENT_ERROR);
        condition.setPageAble(false);
        return marketService.getMarketOrgList(condition);
    }

    /**
     * @Description: 市场所有部门对象集合列表分页查询
     * @Param: [obj]
     * @return: java.lang.Object
     * @Author: cxc
     * @Date: 2018.04.27 15:02
     */
    @PostMapping("/org/obj/search")
    @NotResult
    public Object orgObjSearch(@RequestBody AllCondition condition) {
        ExceptionConditions.checkNotNull(condition.getMarketCode(), StateCode.NO_ARGUMENT_ERROR);
        AllCondition all = new AllCondition();
        all.setPageAble(false);
        all.setMarketCode(condition.getMarketCode());
        List<MarketOrg> marketOrgList = marketService.getMarketOrgList(all);
//        PageInfo.getPageInfo(marketOrgList);
        if (marketOrgList.size() > 0) {
            condition.setOrgIds(marketOrgList.stream().map(MarketOrg::getOrgSerialNo).distinct().collect(Collectors.toList()));
            return organizationServiceClient.orgSearch(condition);
        }
        return Result.getSuccessResult(null);
    }

    /**
     * @Description: 市场所有部门的所有角色
     * @Param: [condition]
     * @return: java.lang.Object
     * @Author: cxc
     * @Date: 2018.04.27 18:07
     */
    @PostMapping("/org/role/search")
    @NotResult
    public Object orgRoleSearch(@RequestBody AllCondition condition) {
        ExceptionConditions.checkNotNull(condition.getMarketCode(), StateCode.NO_ARGUMENT_ERROR);
        AllCondition all = new AllCondition();
        all.setPageAble(false);
        all.setMarketCode(condition.getMarketCode());
        List<MarketOrg> marketOrgList = marketService.getMarketOrgList(all);
        if (marketOrgList.size() > 0) {
            condition.setOrgSerialNos(marketOrgList.stream().map(MarketOrg::getOrgSerialNo).distinct().collect(Collectors.toList()));
            return roleServiceClient.orgSearch(condition);
        }
        return Result.getSuccessResult(null);
    }

    /**
     * @Description: 市场所有部门的所有警种
     * @Param: [condition]
     * @return: java.lang.Object
     * @Author: cxc
     * @Date: 2018.04.27 18:08
     */
    @PostMapping("/org/dictionary/search")
    @NotResult
    public Object orgDictionarySearch(@RequestBody AllCondition condition) {
        ExceptionConditions.checkNotNull(condition.getMarketCode(), StateCode.NO_ARGUMENT_ERROR);
        AllCondition all = new AllCondition();
        all.setPageAble(false);
        all.setMarketCode(condition.getMarketCode());
        List<MarketOrg> marketOrgList = marketService.getMarketOrgList(all);
        if (marketOrgList.size() > 0) {
            condition.setOrgSerialNos(marketOrgList.stream().map(MarketOrg::getOrgSerialNo).distinct().collect(Collectors.toList()));
            return dictionaryServiceServiceClient.orgSearch(condition);
        }
        return Result.getSuccessResult(null);
    }

    /**
     * @Description: 市场所有部门的所有用户
     * @Param: [condition]
     * @return: java.lang.Object
     * @Author: cxc
     * @Date: 2018.04.27 19:34
     */
    @PostMapping("/org/user/search")
    @NotResult
    public Object userSearch(@RequestBody AllCondition condition) throws Exception {
        ExceptionConditions.checkNotNull(condition.getMarketCode(), StateCode.NO_ARGUMENT_ERROR);
        AllCondition all = new AllCondition();
        all.setPageAble(false);
        all.setMarketCode(condition.getMarketCode());
        List<MarketOrg> marketOrgList = marketService.getMarketOrgList(all);
        if (marketOrgList.size() > 0) {
            condition.setOrgSerialNos(marketOrgList.stream().map(MarketOrg::getOrgSerialNo).distinct().collect(Collectors.toList()));
            return userServiceClient.getUserList(JSON.parseObject(JSON.toJSONString(condition), new HashMap<String, Object>().getClass()));
        }
        return Result.getSuccessResult(null);
    }

    /**
     * @Description: 市场所有部门树结构
     * @Param: [condition]
     * @return: java.lang.Object
     * @Author: cxc
     * @Date: 2018.04.27 17:48
     */
    @NotResult
    @PostMapping("/org/tree/search")
    public Object orgSearch(@RequestBody AllCondition condition) {
        ExceptionConditions.checkNotNull(condition.getMarketCode(), StateCode.NO_ARGUMENT_ERROR);
        condition.setPageAble(false);
        List<MarketOrg> marketOrgList = marketService.getMarketOrgList(condition);
        if (marketOrgList.size() > 0) {
            condition.setOrgIds(marketOrgList.stream().map(MarketOrg::getOrgSerialNo).distinct().collect(Collectors.toList()));
            condition.setPageAble(false);
            Object organizationDataObj = organizationServiceClient.orgSearch(condition);
            Result result = JSON.parseObject(JSON.toJSONString(organizationDataObj), Result.class);
            BasePage<?> basePage = JSON.parseObject(JSON.toJSONString(result.getData()), BasePage.class);
            List<Organization> orgList = JSON.parseArray(JSON.toJSONString(basePage.getList()), Organization.class);
            List<OrganizationVo> orgVoList = orgTree(orgList);
            List<String> parentMorgSerialNoList = marketOrgList.stream().filter(morg -> morg.getOrgParentSerialNo().equals(Constants.TOP_LEVEL_ORGANIZATION)).map(MarketOrg::getOrgSerialNo).collect(Collectors.toList());
            return orgVoList.stream().filter(org -> parentMorgSerialNoList.contains(org.getOrgSerialNo())).collect(Collectors.toList());
        }
        return Result.getSuccessResult(null);
    }

    /**
     * @Description: 市场发布的应用查询
     * @Param: [condition] marketCode appName applicationType
     * @return: java.lang.Object
     * @Author: cxc
     * @Date: 2018.04.28 14:18
     */
    @PostMapping("/publish/search")
    @NotResult
    public Object searchPublishApp(@RequestBody AllCondition condition) {
        return appBaseInfoServiceClient.searchPublishApp(condition);
    }

    /**
     * @Description: 双表树结构
     * @Param: [marketOrgList, orgList]
     * @return: java.util.List<com.kingyea.app.market.dept.bean.OrganizationVo>
     * @Author: cxc
     * @Date: 2018.04.27 18:36
     * efe
     */
    private List<OrganizationVo> orgTree(List<Organization> orgList) {
        List<OrganizationVo> orgVoList = orgList.stream().map(org -> {
            OrganizationVo vo = new OrganizationVo();
            BeanUtils.copyProperties(org, vo);
            return vo;
        }).collect(Collectors.toList());
        orgVoList.stream().forEach(vo1 -> {
            vo1.setOrganizationVos(orgVoList.stream().filter(vo2 -> vo1.getOrgSerialNo().equals(vo2.getParentSerialNo())).collect(Collectors.toList()));
        });
        return orgVoList;
//        return orgVoList.stream().filter(vo1 -> vo1.getParentSerialNo().equals(GlobalVar.TOP_LEVEL_ORGANIZATION)).collect(Collectors.toList());
    }

    @RequestMapping(value = "/getOrgNameByRole", method = RequestMethod.POST)
    public Object getOrgNameByRole() throws Exception {
        Object obj = organizationServiceClient.getOrgNameByRole();
        Result result = JSON.parseObject(JSON.toJSONString(obj), Result.class);
        List mapList = JSON.parseObject(JSON.toJSONString(result.getData()), Lists.<Map<String, Object>>newArrayList().getClass());
        return mapList;
    }

}
